From: Aleksey Kladov Date: Wed, 9 Aug 2017 21:54:09 +0000 (+0300) Subject: Allow to skip test code during publishing X-Git-Tag: archive/raspbian/0.35.0-2+rpi1~3^2^2^2^2^2^2^2~22^2~8^2~2^2~4 X-Git-Url: https://dgit.raspbian.org/%22http://www.example.com/cgi/success//%22http:/www.example.com/cgi/success/?a=commitdiff_plain;h=72e3155efe4c6b053eccfcf4d93e33b5b3b7946d;p=cargo.git Allow to skip test code during publishing --- diff --git a/src/cargo/core/manifest.rs b/src/cargo/core/manifest.rs index 140871064..7faebae6c 100644 --- a/src/cargo/core/manifest.rs +++ b/src/cargo/core/manifest.rs @@ -21,7 +21,7 @@ pub struct Manifest { summary: Summary, targets: Vec, links: Option, - warnings: Vec, + warnings: Vec, exclude: Vec, include: Vec, metadata: ManifestMetadata, @@ -32,6 +32,15 @@ pub struct Manifest { original: Rc, } +/// When parsing `Cargo.toml`, some warnings should silenced +/// if the manifest comes from a dependency. `ManifestWarning` +/// allows this delayed emission of warnings. +#[derive(Clone, Debug)] +pub struct DelayedWarning { + pub message: String, + pub is_critical: bool +} + #[derive(Clone, Debug)] pub struct VirtualManifest { replace: Vec<(PackageIdSpec, Dependency)>, @@ -252,7 +261,7 @@ impl Manifest { pub fn summary(&self) -> &Summary { &self.summary } pub fn targets(&self) -> &[Target] { &self.targets } pub fn version(&self) -> &Version { self.package_id().version() } - pub fn warnings(&self) -> &[String] { &self.warnings } + pub fn warnings(&self) -> &[DelayedWarning] { &self.warnings } pub fn profiles(&self) -> &Profiles { &self.profiles } pub fn publish(&self) -> bool { self.publish } pub fn replace(&self) -> &[(PackageIdSpec, Dependency)] { &self.replace } @@ -266,7 +275,11 @@ impl Manifest { } pub fn add_warning(&mut self, s: String) { - self.warnings.push(s) + self.warnings.push(DelayedWarning { message: s, is_critical: false }) + } + + pub fn add_critical_warning(&mut self, s: String) { + self.warnings.push(DelayedWarning { message: s, is_critical: true }) } pub fn set_summary(&mut self, summary: Summary) { diff --git a/src/cargo/ops/cargo_compile.rs b/src/cargo/ops/cargo_compile.rs index de2cc1e2b..d5b8e85e6 100644 --- a/src/cargo/ops/cargo_compile.rs +++ b/src/cargo/ops/cargo_compile.rs @@ -33,6 +33,7 @@ use core::resolver::Resolve; use ops::{self, BuildOutput, Executor, DefaultExecutor}; use util::config::Config; use util::{CargoResult, profile}; +use util::errors::{CargoResultExt, CargoError}; /// Contains information about how a package should be compiled. pub struct CompileOptions<'a> { @@ -177,8 +178,15 @@ pub fn compile_with_exec<'a>(ws: &Workspace<'a>, exec: Arc) -> CargoResult> { for member in ws.members() { - for key in member.manifest().warnings().iter() { - options.config.shell().warn(key)? + for warning in member.manifest().warnings().iter() { + if warning.is_critical { + let err: CargoResult<_> = Err(CargoError::from(warning.message.to_owned())); + return err.chain_err(|| { + format!("failed to parse manifest at `{}`", member.manifest_path().display()) + }) + } else { + options.config.shell().warn(&warning.message)? + } } } compile_ws(ws, None, options, exec) diff --git a/src/cargo/util/toml/mod.rs b/src/cargo/util/toml/mod.rs index 78b86ec91..c114b0211 100644 --- a/src/cargo/util/toml/mod.rs +++ b/src/cargo/util/toml/mod.rs @@ -501,6 +501,7 @@ impl TomlManifest { -> CargoResult<(Manifest, Vec)> { let mut nested_paths = vec![]; let mut warnings = vec![]; + let mut errors = vec![]; let project = me.project.as_ref().or_else(|| me.package.as_ref()); let project = project.ok_or_else(|| { @@ -517,7 +518,8 @@ impl TomlManifest { // If we have no lib at all, use the inferred lib if available // If we have a lib with a path, we're done // If we have a lib with no path, use the inferred lib or_else package name - let targets = targets(me, package_name, package_root, &project.build, &mut warnings)?; + let targets = targets(me, package_name, package_root, &project.build, + &mut warnings, &mut errors)?; if targets.is_empty() { debug!("manifest has no build targets"); @@ -653,7 +655,10 @@ impl TomlManifest { `license-file` is necessary".to_string()); } for warning in warnings { - manifest.add_warning(warning.clone()); + manifest.add_warning(warning); + } + for error in errors { + manifest.add_critical_warning(error); } Ok((manifest, nested_paths)) diff --git a/src/cargo/util/toml/targets.rs b/src/cargo/util/toml/targets.rs index d7e6af08c..54fd6220e 100644 --- a/src/cargo/util/toml/targets.rs +++ b/src/cargo/util/toml/targets.rs @@ -25,7 +25,8 @@ pub fn targets(manifest: &TomlManifest, package_name: &str, package_root: &Path, custom_build: &Option, - warnings: &mut Vec) + warnings: &mut Vec, + errors: &mut Vec) -> CargoResult> { let mut targets = Vec::new(); @@ -43,15 +44,15 @@ pub fn targets(manifest: &TomlManifest, ); targets.extend( - clean_examples(manifest.example.as_ref(), package_root)? + clean_examples(manifest.example.as_ref(), package_root, errors)? ); targets.extend( - clean_tests(manifest.test.as_ref(), package_root)? + clean_tests(manifest.test.as_ref(), package_root, errors)? ); targets.extend( - clean_benches(manifest.bench.as_ref(), package_root, warnings)? + clean_benches(manifest.bench.as_ref(), package_root, warnings, errors)? ); // processing the custom build script @@ -191,7 +192,11 @@ fn clean_bins(toml_bins: Option<&Vec>, } else { None } - })?; + }); + let path = match path { + Ok(path) => path, + Err(e) => bail!("{}", e), + }; let mut target = Target::bin_target(&bin.name(), path, bin.required_features.clone()); @@ -221,11 +226,12 @@ fn clean_bins(toml_bins: Option<&Vec>, } fn clean_examples(toml_examples: Option<&Vec>, - package_root: &Path) + package_root: &Path, + errors: &mut Vec) -> CargoResult> { let targets = clean_targets("example", "example", toml_examples, inferred_examples(package_root), - package_root)?; + package_root, errors)?; let mut result = Vec::new(); for (path, toml) in targets { @@ -244,10 +250,11 @@ fn clean_examples(toml_examples: Option<&Vec>, } fn clean_tests(toml_tests: Option<&Vec>, - package_root: &Path) -> CargoResult> { + package_root: &Path, + errors: &mut Vec) -> CargoResult> { let targets = clean_targets("test", "test", toml_tests, inferred_tests(package_root), - package_root)?; + package_root, errors)?; let mut result = Vec::new(); for (path, toml) in targets { @@ -261,7 +268,8 @@ fn clean_tests(toml_tests: Option<&Vec>, fn clean_benches(toml_benches: Option<&Vec>, package_root: &Path, - warnings: &mut Vec) -> CargoResult> { + warnings: &mut Vec, + errors: &mut Vec) -> CargoResult> { let mut legacy_bench_path = |bench: &TomlTarget| { let legacy_path = package_root.join("src").join("bench.rs"); if !(bench.name() == "bench" && legacy_path.exists()) { @@ -283,6 +291,7 @@ fn clean_benches(toml_benches: Option<&Vec>, let targets = clean_targets_with_legacy_path("benchmark", "bench", toml_benches, inferred_benches(package_root), package_root, + errors, &mut legacy_bench_path)?; let mut result = Vec::new(); @@ -299,12 +308,14 @@ fn clean_benches(toml_benches: Option<&Vec>, fn clean_targets(target_kind_human: &str, target_kind: &str, toml_targets: Option<&Vec>, inferred: Vec<(String, PathBuf)>, - package_root: &Path) + package_root: &Path, + errors: &mut Vec) -> CargoResult> { clean_targets_with_legacy_path(target_kind_human, target_kind, toml_targets, inferred, package_root, + errors, &mut |_| None) } @@ -312,6 +323,7 @@ fn clean_targets_with_legacy_path(target_kind_human: &str, target_kind: &str, toml_targets: Option<&Vec>, inferred: Vec<(String, PathBuf)>, package_root: &Path, + errors: &mut Vec, legacy_path: &mut FnMut(&TomlTarget) -> Option) -> CargoResult> { let toml_targets = match toml_targets { @@ -332,7 +344,14 @@ fn clean_targets_with_legacy_path(target_kind_human: &str, target_kind: &str, validate_unique_names(&toml_targets, target_kind)?; let mut result = Vec::new(); for target in toml_targets { - let path = target_path(&target, &inferred, target_kind, package_root, legacy_path)?; + let path = target_path(&target, &inferred, target_kind, package_root, legacy_path); + let path = match path { + Ok(path) => path, + Err(e) => { + errors.push(e); + continue + }, + }; result.push((path, target)); } Ok(result) @@ -459,7 +478,7 @@ fn target_path(target: &TomlTarget, inferred: &[(String, PathBuf)], target_kind: &str, package_root: &Path, - legacy_path: &mut FnMut(&TomlTarget) -> Option) -> CargoResult { + legacy_path: &mut FnMut(&TomlTarget) -> Option) -> Result { if let Some(ref path) = target.path { // Should we verify that this path exists here? return Ok(package_root.join(&path.0)); @@ -478,9 +497,8 @@ fn target_path(target: &TomlTarget, if let Some(path) = legacy_path(target) { return Ok(path); } - - bail!("can't find `{name}` {target_kind}, specify {target_kind}.path", - name = name, target_kind = target_kind) + Err(format!("can't find `{name}` {target_kind}, specify {target_kind}.path", + name = name, target_kind = target_kind)) } (None, Some(_)) => unreachable!() } diff --git a/tests/build.rs b/tests/build.rs index 8c7b0c59b..535b532ef 100644 --- a/tests/build.rs +++ b/tests/build.rs @@ -3413,7 +3413,7 @@ fn dir_and_file_with_same_name_in_bin() { .file("src/bin/foo.rs", "fn main() {}") .file("src/bin/foo/main.rs", "fn main() {}"); - assert_that(p.cargo_process("build"), + assert_that(p.cargo_process("build"), execs().with_status(101) .with_stderr_contains("\ [..]found duplicate binary name foo, but all binary targets must have a unique name[..] diff --git a/tests/test.rs b/tests/test.rs index 686157a32..f61f19c75 100644 --- a/tests/test.rs +++ b/tests/test.rs @@ -2700,3 +2700,42 @@ fn cyclic_dev() { assert_that(p.cargo_process("test").arg("--all"), execs().with_status(0)); } + +#[test] +fn publish_a_crate_without_tests() { + Package::new("testless", "0.1.0") + .file("Cargo.toml", r#" + [project] + name = "testless" + version = "0.1.0" + exclude = ["tests/*"] + + [[test]] + name = "a_test" + "#) + .file("src/lib.rs", "") + + // In real life, the package will have a test, + // which would be excluded from .crate file by the + // `exclude` field. Our test harness does not honor + // exclude though, so let's just not add the file! + // .file("tests/a_test.rs", "") + + .publish(); + + let p = project("foo") + .file("Cargo.toml", r#" + [project] + name = "foo" + version = "0.1.0" + + [dependencies] + testless = "0.1.0" + "#) + .file("src/lib.rs", ""); + p.build(); + + assert_that(p.cargo("test"), execs().with_status(0)); + assert_that(p.cargo("test").arg("--package").arg("testless"), + execs().with_status(0)); +}